/*************************************************************
 * Title: 
 * Description: 
 * Author: Snow Huang
 * Email: Shaobin.Software@gmail.com Shaobin_Software@163.com
 * CreateTime: 2010-8-1 下午03:25:12
 * Copyright © 落羽社区 All right reserved
 ************************************************************/
package snow.core.domain.query;

import java.util.ArrayList;
import java.util.List;

import org.springframework.util.Assert;

import snow.core.domain.query.operator.ComparisonOperator;
import snow.core.domain.query.operator.MultiOperator;
import snow.core.domain.query.operator.UnaryOperator;
import snow.core.util.toolkit.CollectionHelper;

/**
 * 
 */
public class Query<Entity> {

	private int startIndex = -1; // 查询的起始位置
	private int limitSize = -1; // 每页显示大小
	private int orderIndex = 0; // 排序顺序
	private int criterionIndex = 0; // 

	private final Class<Entity> entityClass; // 实体类的Class对象

	private final List<Order> orders = new ArrayList<Order>(3); // 排序对象
	private final List<Criterion> criteria = new ArrayList<Criterion>(); // 查询条件

	protected Query(Class<Entity> entityClass) {
		Assert.notNull(entityClass);
		this.entityClass = entityClass;
	}

	private void addCriterion(Criterion criterion) {
		criteria.add(criterionIndex++, criterion);
	}

	protected final void addCriterion(String propertyName, List<? extends Object> values) {
		Assert.notEmpty(values);
		addCriterion(new Criterion(propertyName, values, MultiOperator.IN));
	}

	protected final void addCriterion(String propertyName, Object value, ComparisonOperator operator) {
		Assert.notNull(value);
		Assert.notNull(operator);
		addCriterion(new Criterion(propertyName, value, operator));
	}

	protected final void addCriterion(String propertyName, Object value1, Object value2) {
		Assert.notNull(value1);
		Assert.notNull(value2);
		Object[] values = { value1, value2 };
		addCriterion(new Criterion(propertyName, values, MultiOperator.BETWEEN));
	}

	protected final void addCriterion(String propertyName, UnaryOperator operator) {
		Assert.notNull(operator);
		addCriterion(new Criterion(propertyName, null, operator));
	}

	private Query<Entity> addOrder(Order order) {
		orders.add(orderIndex++, order);
		return this;
	}

	public final Query<Entity> asc(String propertyName) {
		return addOrder(new Order(propertyName, true));
	}

	public final Query<Entity> desc(String propertyName) {
		return addOrder(new Order(propertyName, false));
	}

	public List<Criterion> getCriteria() {
		return CollectionHelper.getNewListFrom(criteria);
	}

	/**
	 * @return the entityClass
	 */
	public final Class<Entity> getEntityClass() {
		return entityClass;
	}

	/**
	 * @return the limitSize
	 */
	public int getLimitSize() {
		return limitSize;
	}

	/**
	 * @return the orders
	 */
	public final List<Order> getOrders() {
		return CollectionHelper.getNewListFrom(orders);
	}

	/**
	 * @return the startIndex
	 */
	public int getStartIndex() {
		return startIndex;
	}

	/**
	 * @param limitSize
	 *            the limitSize to set
	 */
	public void setLimitSize(int limitSize) {
		this.limitSize = limitSize;
	}

	/**
	 * @param startIndex
	 *            the startIndex to set
	 */
	public void setStartIndex(int startIndex) {
		this.startIndex = startIndex;
	}
}
